"""
HumanInputLoopAgent - 通用人机交互父类

这是一个抽象父类，提供了完整的人机交互功能，包括：
- LangGraph interrupt 机制支持
- 交互状态管理
- 用户响应处理
- 流式交互支持
- 异常处理

子类只需要专注于具体的业务逻辑，无需重复实现人机交互的通用功能。

作者：AI Assistant
版本：1.0.0
日期：2024
"""
from datetime import datetime
from typing import Dict, Any, List, TypedDict, Optional

from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph.state import CompiledStateGraph
from langgraph.types import interrupt

from AIAgents.streamableAgent import StreamableAgent
from config.logging_config import get_logger
# 导入全局工具字典
from constant.tool_dict_config import toolDictConfig

# 导入全局工具字典
# 设置日志记录器
logger = get_logger(__name__)


class HumanInteractionState(TypedDict):
    """人机交互Agent的基础状态定义"""
    # 基础输入
    input: str
    original_input: str

    # 对话历史
    messages: List[Dict[str, Any]]

    # 当前思考和计划
    current_thought: str
    action_plan: Dict[str, Any]

    # 人机交互相关
    need_approval: bool  # 是否需要用户批准
    approval_message: str  # 等待批准的消息
    tool_info: Dict[str, Any]  # 工具信息
    user_approved: Optional[bool]  # 用户是否批准，None表示未回复
    interaction_id: str  # 交互ID，用于追踪
    need_human_interaction: bool  # 是否需要人机交互
    human_interaction_message: Dict[str, Any]  # 人机交互消息
    user_confirmation: bool  # 用户确认结果

    # 工具执行相关
    selected_tool: Optional[str]  # 选择的工具名称
    tool_parameters: Dict[str, Any]  # 工具参数
    tool_results: List[Dict[str, Any]]  # 工具执行结果

    # 状态控制
    should_continue: bool
    iteration_count: int
    max_iterations: int

    # 输出相关
    final_response: str
    success: bool
    error: str


class HumanInputLoopAgent(StreamableAgent):
    """通用人机交互Agent父类 - 提供完整的人机交互功能"""

    def __init__(self, **kwargs):
        # 人机交互相关属性
        self.current_config = None
        self.checkpointer = MemorySaver()
        self.interaction_states = {}  # 存储交互状态的字典

        # 调用父类初始化
        super().__init__(**kwargs)

    def _build_graph(self) -> CompiledStateGraph:
        """构建Agent的工作流图"""
        pass

    # ==================== 人机交互通用方法 ====================
    def create_human_interaction_message(self, tool_name: str, tool_params: Dict[str, Any],
                                         interaction_type: str = "tool_confirmation",
                                         interaction_id: str = None,
                                         server_name: str = None) -> Dict[str, Any]:
        """创建人机交互消息"""
        # 生成交互ID
        if not interaction_id:
            interaction_id = f"interaction_{int(datetime.now().timestamp() * 1000)}"

        # 处理MCP工具名称格式
        display_tool_name = tool_name
        if interaction_type == "mcp_confirmation" and server_name and not tool_name.startswith(f"{server_name}."):
            display_tool_name = f"{server_name}.{tool_name}"

        # 构建批准消息
        if interaction_type == "tool_confirmation":
            approval_message = f"即将执行工具：{display_tool_name}"
        elif interaction_type == "mcp_confirmation":
            approval_message = f"即将执行MCP工具：{display_tool_name}"
        elif interaction_type == "human_ask":
            approval_message = "当前任务已完成，本次任务是否还有其他需要补充或处理的问题？"
        else:
            approval_message = f"即将执行操作：{display_tool_name}"

        if tool_params and interaction_type in ["tool_confirmation", "mcp_confirmation"]:
            approval_message += f"\n参数：{tool_params}"
        
        if interaction_type in ["tool_confirmation", "mcp_confirmation"]:
            approval_message += "\n\n是否确认执行？"

        # 构建工具信息
        tool_info = {
            "tool_name": display_tool_name,
            "parameters": tool_params,
            "description": approval_message,
            "interaction_id": interaction_id,
            "interaction_type": interaction_type
        }

        # 创建交互消息
        interaction_message = {
            "type": "human_interaction",
            "content": approval_message,
            "timestamp": datetime.now().isoformat(),
            "data": {
                "interaction_id": interaction_id,
                "interaction_type": interaction_type,
                "tool_info": tool_info,
                "query": approval_message,
                "responded": False,
                "responding": False,
                "approved": None
            }
        }

        # 保存交互状态
        self.interaction_states[interaction_id] = {
            "config": getattr(self, 'current_config', None),
            "tool_name": display_tool_name,
            "tool_params": tool_params,
            "server_name": server_name,
            "interaction_type": interaction_type,
            "user_approved": None,
            "responded": False,
            "timestamp": datetime.now().isoformat()
        }

        logger.info(f"🤝 创建人机交互消息，交互ID：{interaction_id}")
        return interaction_message

    def create_human_interaction_from_state(self, state: Dict[str, Any],
                                            interaction_id_prefix: str = "interaction") -> Dict[str, Any]:
        """从状态中创建人机交互消息的通用方法 - 支持NavigationAgent等子类"""
        try:
            # 从状态中提取智能响应信息
            intelligent_response = state.get("intelligent_response", {})
            parsed_action = intelligent_response.get("action", "")

            # 构建工具信息
            tool_name = ""
            tool_params = {}
            server_name = None
            interaction_type = "tool_confirmation"

            if "tool" in parsed_action:
                tool_name = intelligent_response.get("tool_name", "")
                tool_params = intelligent_response.get("tool_params", {})
                interaction_type = "tool_confirmation"

            elif "mcp" in parsed_action:
                server_name = intelligent_response.get("server_name", "")
                tool_name = intelligent_response.get("tool_name", "")
                tool_params = intelligent_response.get("mcp_params", {})
                interaction_type = "mcp_confirmation"
            elif "answer" in parsed_action:
                interaction_type = "human_ask"

            # 生成交互ID
            interaction_id = f"{interaction_id_prefix}_{int(datetime.now().timestamp() * 1000)}"

            # 使用通用方法创建交互消息
            return self.create_human_interaction_message(
                tool_name=tool_name,
                tool_params=tool_params,
                interaction_type=interaction_type,
                interaction_id=interaction_id,
                server_name=server_name
            )

        except Exception as e:
            logger.error(f"从状态创建人机交互消息失败: {e}")
            # 返回默认的交互消息
            interaction_id = f"{interaction_id_prefix}_{int(datetime.now().timestamp() * 1000)}"
            return self.create_human_interaction_message(
                tool_name="未知操作",
                tool_params={},
                interaction_type="tool_confirmation",
                interaction_id=interaction_id
            )

    def check_tool_needs_approval(self, tool_name: str) -> bool:
        """检查工具是否需要人机交互 - 通用方法"""
        try:
            # 导入全局工具字典
            from constant.tool_dict_config import toolDictConfig

            if not toolDictConfig.is_initialized():
                logger.warning("全局工具字典未初始化，默认不需要人机交互")
                return False

            # 从全局工具字典获取工具信息
            for tool_id, tool_info in toolDictConfig.get_base_tools_dict().items():
                if tool_info.get('tool_name') == tool_name:
                    human_flag = tool_info.get('human_interactive_flag', 0)
                    return human_flag == 1

            logger.warning(f"未找到工具 {tool_name} 的配置信息")
            return False

        except Exception as e:
            logger.error(f"检查工具人机交互配置失败: {e}")
            return False

    def check_mcp_needs_approval(self, server_name: str, tool_name: str) -> bool:
        """检查MCP工具是否需要人机交互 - 通用方法"""
        try:

            if not toolDictConfig.is_initialized():
                logger.warning("全局工具字典未初始化，默认不需要人机交互")
                return False

            # 从全局工具字典获取MCP工具信息
            for tool_id, tool_info in toolDictConfig.get_mcp_tools_dict().items():
                if tool_info.get('tool_name') == tool_name:
                    human_flag = tool_info.get('human_interactive_flag', 0)
                    return human_flag == 1

            logger.warning(f"未找到MCP工具 {server_name}:{tool_name} 的配置信息")
            return False

        except Exception as e:
            logger.error(f"检查MCP工具人机交互配置失败: {e}")
            return False

    async def handle_user_response(self, interaction_id: str, approved: bool, message: str = None) -> bool:
        """处理用户响应 - 更新interaction_states"""
        logger.info(f"收到用户响应 - 交互ID：{interaction_id}，批准：{approved}")

        # 检查交互ID是否存在
        if interaction_id not in self.interaction_states:
            logger.error(f"未找到交互ID：{interaction_id}")
            return False

        try:
            # 更新交互状态
            self.interaction_states[interaction_id].update({
                "user_approved": approved,
                "responded": True,
                "response_timestamp": datetime.now().isoformat()
            })

            # 保存用户消息
            if message and message.strip():
                self.interaction_states[interaction_id]["user_message"] = message
                logger.info(f"✅ 用户补充消息已保存：{message}")

            return True

        except Exception as e:
            logger.error(f"处理用户响应失败：{e}")
            return False

    def _should_skip_node_update(self, node_name: str) -> bool:
        """判断是否跳过节点更新消息 - 重写父类方法，添加人机交互相关节点"""
        return node_name in ["finish", "check_human", "human"]

    def _handle_interrupt(self, chunk: Dict[str, Any], config: Dict[str, Any]) -> Dict[str, Any]:
        """处理中断信息，构建人机交互消息"""
        try:
            logger.info("🔴 检测到中断，发送人机交互消息")

            interrupt_data = chunk["__interrupt__"][0]
            interrupt_value = interrupt_data.value

            # 提取交互ID
            interaction_id = interrupt_value.get("interaction_id", "")

            # 构建工具信息格式
            tool_info = interrupt_value.get("tool_info", {})
            formatted_tool_info = {
                "tool_name": tool_info.get("tool_name", ""),
                "description": tool_info.get("description", ""),
                "parameters": tool_info.get("parameters", {}),
                "interaction_id": interaction_id
            }

            # 发送人机交互消息
            interaction_message = {
                "type": "human_interaction",
                "content": interrupt_value.get("query", "需要您的确认"),
                "timestamp": datetime.now().isoformat(),
                "data": {
                    "interaction_id": interaction_id,
                    "interaction_type": interrupt_value.get("interaction_type", "tool_confirmation"),
                    "tool_info": formatted_tool_info,
                    "query": interrupt_value.get("query", ""),
                    "responded": False,
                    "responding": False,
                    "approved": None
                }
            }

            # 保存中断状态
            self.interaction_states[interaction_id] = {
                "config": config,
                "interrupt_data": interrupt_data,
                "interrupt_value": interrupt_value,
                "current_state": chunk,
                "user_approved": None,
                "responded": False,
                "timestamp": datetime.now().isoformat()
            }

            logger.info(f"中断状态已保存，交互ID：{interaction_id}")
            return interaction_message

        except Exception as e:
            logger.error(f"❌ 处理中断失败: {str(e)}")
            return None

    def create_interrupt_and_update_state(self, state: Dict[str, Any],
                                          interaction_id_prefix: str = "interaction") -> Dict[str, Any]:
        """创建interrupt并更新状态"""
        # 创建交互消息
        interaction_message = self.create_human_interaction_from_state(state, interaction_id_prefix)

        # 提取交互相关信息
        interaction_data = interaction_message["data"]
        interaction_id = interaction_data["interaction_id"]
        tool_info = interaction_data["tool_info"]
        approval_message = interaction_data["query"]
        interaction_type = interaction_data["interaction_type"]

        # 使用interrupt函数暂停执行，等待用户输入
        logger.info(f"🔴 执行interrupt，等待用户批准 - 交互ID：{interaction_id}")
        user_decision = interrupt({
            "query": approval_message,
            "tool_info": tool_info,
            "interaction_type": interaction_type,
            "interaction_id": interaction_id
        })

        logger.info(f"✅ 收到用户决策：{user_decision}")

        # 更新状态
        state.update({
            "user_confirmation": user_decision,
            "interaction_id": interaction_id,
            "human_interaction_message": interaction_message
        })

        return state

    def get_interaction_state(self, interaction_id: str) -> Optional[Dict[str, Any]]:
        """获取交互状态 - 通用方法"""
        return self.interaction_states.get(interaction_id)

    def clear_interaction_state(self, interaction_id: str) -> bool:
        """清理交互状态 - 通用方法"""
        try:
            if interaction_id in self.interaction_states:
                del self.interaction_states[interaction_id]
                logger.info(f"已清理交互状态：{interaction_id}")
                return True
            return False
        except Exception as e:
            logger.error(f"清理交互状态失败：{e}")
            return False

    def process(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
        """同步处理方法 - 不实现，使用流式处理"""
        logger.warning(f"{self.__class__.__name__}不支持同步处理，请使用process_stream方法")
        return {
            "success": False,
            "error": "不支持同步处理，请使用流式处理"
        }
